import java.net.*;
import java.io.*;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 *	@file AppFinder.java
 *	@author David Meehan
 *	@version 2/16/2013
 *	AppFinder is a program that downloads attachments from student
 *	google sites to the user's local computer. 
 */
public class AppFinder
{
	/**
	 *	Main method which runs the program.
	 *	@param String[] args - arguments sent along with the call to
	 *	run the program
	 */
	public static void main(String[] args) {
		new AppFinder();
	}
	// INSTANCE VARIABLES ////////////////////////////////////////////
	private String[][] students; // List of students and their sites
	private String[] tags;
	private String urlBase;
	
	/**
	 *	Constructs an AppFinder
	 */
	public AppFinder() {
		urlBase = "https://sites.google.com/";
		
		Scanner iscan = new Scanner(System.in);
		System.out.print("Project Tags: ");
		tags = iscan.nextLine().toLowerCase().split(" ");
		readFile();
		processStudentFiles();
	}
	
	/**
	 *	Reads in the roster file and obtains all information on
	 *	students. Student file must be formatted as <name-hyphen-
	 *	separated> <Google Site>If it cannot load the file, aborts 
	 *	the program
	 */
	public void readFile() {
		try {
			Scanner fscan = new Scanner(new File("roster.txt"));
			students = new String[fscan.nextInt()][2];
			int i=0;
			while(fscan.hasNext()) {
				students[i][0] = fscan.next();
				students[i][1] = fscan.next();
				i++;
			}
		} catch(IOException e) {
			System.out.println("Could not find class roster! Program aborted.");
			System.exit(0);
		}
	}
	/**
	 *	Searched all student sites by attempting to find the page
	 *	for the assignment. If it finds the page, the program then
	 *	attempts to search the found page for attachment files and
	 *	then downloads them to the users computer.
	 */
	public void processStudentFiles() {
		Pattern pattern = Pattern.compile("/site/\\S*d=1");
		for(int i=0; i<students.length; i++) {
			String link = findProjectPage(i);
			int remaining = (int)Math.round((((double)i/(double)
					students.length)*100));
			System.out.println("Completed " + students[i][0] + 
					" (" + remaining + "% Complete)");
			if(link == null) {
				System.out.println(" - Site Not Found");
				continue;
			}
			searchPageForFile(link, pattern, students[i][0]);
		}
		System.out.println("Done!");
	}
	
	/**
	 *	@param int i - the index for the current student in students[][]
	 *	Searches for the student assignment page denoted by the provided
	 *	tags. Tags will be sequentially concatenated and then the
	 *	new page will be searched for. For this reason, the order the 
	 *	tags are provided is important. If a return code 200 is returned
	 *	by a page, the site was found. Otherwise keep trying.
	 */
	public String findProjectPage(int i) {
		String link = urlBase + "/site/" + students[i][1];
		boolean validUrl= false;
		for(int j=0; j<tags.length; j++) {
			try {
				link = (j==0) ? link + tags[j] : link + "-" + tags[j];
				URL test = new URL(link); 
				HttpURLConnection testConnection = (HttpURLConnection)
						test.openConnection();
				testConnection.setRequestMethod("GET"); 
				testConnection.connect();
				int returnCode = testConnection.getResponseCode();
				if(returnCode == 200) {
					validUrl = true;
					break;
				}
			} catch(IOException e) {
				
			}
		}
		if(validUrl)
			return link;
		return null;
	}
	
	/**
	 *	@param String source - URL for the attachment
	 *	@param String name - Name of the student
	 *	Downloads the file from the URL by opening an input stream to
	 *	the URL and writing the buffer data returned into a file. Reads
	 *	the input stream first into a Byte array and then writes that
	 *	buffer to the file. 
	 */
	public void downloadFile(String source, String name) {
		String[] s = source.split("/");
		s = s[s.length-1].split("\\?");
		String fname = s[0];
		System.out.println(" - Downloaded: " + s[0]);
		String dir = getStudentDir(name) + "/";
		try {
			String line;
			URL url = new URL(urlBase + source);
			HttpURLConnection connection = (HttpURLConnection) 
					url.openConnection();
			connection.setRequestMethod("GET");
			InputStream in = connection.getInputStream();
			FileOutputStream out = new FileOutputStream(dir + fname);
			byte[] buffer = new byte[1024];
			int n = in.read(buffer);
			while (n >= 0) {
				out.write(buffer, 0, n);
				n = in.read(buffer);
			}
			out.flush();
		} catch (MalformedURLException e) {
					e.printStackTrace();
		} catch (IOException e) {
				 e.printStackTrace();
		}
	}
	
	/**
	 *	@param String name - Name of student
	 *	@return String - the absolute path to the output dir
	 *	Returns the path to the directory this program will write the
	 *	attchment files to. If no such directory exists, creates it.
	 */
	public String getStudentDir(String name) {
		File file = new File("Results/" + name + "/");
		if(!file.isDirectory()) {
			file.mkdirs();
		}
		return file.getAbsolutePath();
	}
	
	/**
	 *	@param String page - The url link to the assignment
	 *	@param Pattern pattern - the pattern to match
	 *	@param String name - Student name
	 *	Reads in an input stream from the student's assigmment page
	 *	and searches the html for links to attachments on that page.
	 *	Any matches will be downloaded.
	 */
	public void searchPageForFile(String page, Pattern pattern, String name) {
		try {
			URL searchURL = new URL(page);
			BufferedReader reader = new BufferedReader(new 
					InputStreamReader(searchURL.openStream()));
			String line;
			while((line = reader.readLine()) != null) {
				Matcher match = pattern.matcher(line);
				while(match.find()) {
					downloadFile(match.group(0), name);
				}
			}
		} catch(MalformedURLException e) {
		} catch(IOException e) {
		}
	}
}